/*
 * NyuObject.hpp
 *
 *  Created on: 2010/04/24
 *      Author: mitsu
 */

#ifndef NYUOBJECT_HPP_
#define NYUOBJECT_HPP_

#include "NyuValue.hpp"
#include "NyuContext.hpp"
#include "NyuHash.hpp"

class NyuString;
class NyuObject {
public:
    NyuObject();
    NyuObject(NyuObject* proto);
    virtual ~NyuObject();

    NyuInt to_int(NyuContext* c) {
        return NYU_VALUE_TO_INT(to_intval(c));
    }

    virtual NyuValue to_intval(NyuContext* c);
    virtual NyuString* to_str(NyuContext* c);
    virtual unsigned int hash() const;

    virtual NyuValue getCall(NyuContext* c);

    virtual NyuValue opNot(NyuContext* c, bool is_tail = false);
    virtual NyuValue opInvert(NyuContext* c, bool is_tail = false);
    virtual NyuValue opPos(NyuContext* c, bool is_tail = false);
    virtual NyuValue opNeg(NyuContext* c, bool is_tail = false);
    virtual NyuValue opIncr(NyuContext* c, bool is_tail = false);
    virtual NyuValue opDecr(NyuContext* c, bool is_tail = false);

    virtual NyuValue opPostIncr(NyuContext* c, bool is_tail = false);
    virtual NyuValue opPostDecr(NyuContext* c, bool is_tail = false);

    virtual NyuValue opAdd(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opSub(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opMul(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opDiv(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opMod(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opLShift(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opRShift(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opLt(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opLe(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opGt(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opGe(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opOr(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opXor(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opAnd(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opEq(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opNe(NyuValue other, NyuContext* c, bool is_tail = false);

    virtual NyuValue opIAdd(NyuValue other, NyuContext* c, bool is_tail = false);
    virtual NyuValue opISub(NyuValue other, NyuContext* c, bool is_tail = false);

    virtual NyuValue revEqStr(const char* str, NyuContext* c, bool is_tail = false);

    virtual NyuValue opIAddSlot(NyuObject* key, NyuValue val, NyuContext* c,
                                bool is_tail = false);
    virtual NyuValue opISubSlot(NyuObject* key, NyuValue val, NyuContext* c,
                                bool is_tail = false);

    virtual void putSlot(NyuObject* key, NyuValue val, NyuContext* c);
    virtual NyuValue getSlot(NyuObject* key, NyuContext* c);

    virtual NyuValue getitem(NyuValue idx, NyuContext* c);
    virtual void putitem(NyuValue idx, NyuValue val, NyuContext* c);

    virtual NyuValue getLength(NyuContext* c);
    virtual NyuValue push(NyuContext* c);
    virtual NyuValue pop(NyuContext* c);

    virtual void copyChildren(bool* has_new_obj = 0);

    static void* operator new(size_t size);
    static void* operator new(size_t size, void* p);

protected:
    void addSlot(NyuObject* key, NyuValue val, NyuContext* c);

private:
    unsigned int nslots_;
    unsigned int slots_capacity_;
    NyuValue* slots_;
    NyuHash<NyuObject*, unsigned int> slot_tbl_;
};

#endif /* NYUOBJECT_HPP_ */
